﻿using Manon.Autofac;
using Manon.Core.Extensions;
using Manon.Gateway.Api.Common;
using Manon.Gateway.ApplicationCore.Dtos.Routes;
using Manon.Gateway.ApplicationCore.Interfaces;
using Ocelot.Cache;
using Ocelot.Configuration.File;
using Ocelot.Configuration.Repository;
using Ocelot.Logging;
using Ocelot.Responses;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Manon.Gateway.Api.Repository
{
    public class MysqlFileConfigurationRepository : IFileConfigurationRepository
    {
        private readonly IOcelotCache<FileConfiguration> _cache;
        private readonly IOcelotLogger _logger;
        private readonly GatewayOption _options;


        public MysqlFileConfigurationRepository(IOcelotCache<FileConfiguration> cache, IOcelotLoggerFactory loggerFactory, GatewayOption options)
        {
            _cache = cache;
            _logger = loggerFactory.CreateLogger<MysqlFileConfigurationRepository>();
            _options = options;
        }
        public async Task<Response<FileConfiguration>> Get()
        {
            var config = _cache.Get(_options.CachePrefix + "Configuration", "");

            if (config != null)
            {
                return new OkResponse<FileConfiguration>(config);
            }

            var file = new FileConfiguration();
            try
            {
                var glb = new FileGlobalConfiguration();
                var globalConfigurationService = Resolver.Resolve<IGlobalConfigurationService>();
                var routeService = Resolver.Resolve<IRouteService>();

                var result = await globalConfigurationService.GetGlobalConfiguration();
                if (result == null)
                {
                    return new OkResponse<FileConfiguration>(file);
                }
                var allRoutes = await routeService.GetAllRoutes();

                glb.BaseUrl = result.BaseUrl;
                glb.DownstreamScheme = result.DownstreamScheme;
                glb.RequestIdKey = result.RequestIdKey;
                glb.HttpHandlerOptions = new FileHttpHandlerOptions()
                {
                    AllowAutoRedirect = result.HttpHandler_AllowAutoRedirect,
                    UseCookieContainer = result.HttpHandler_UseCookieContainer,
                    UseProxy = result.HttpHandler_UseProxy,
                    UseTracing = result.HttpHandler_UseTracing
                };
                glb.RateLimitOptions = new FileRateLimitOptions()
                {
                    ClientIdHeader = result.RateLimit_ClientIdHeader,
                    DisableRateLimitHeaders = result.RateLimit_DisableRateLimitHeaders,
                    HttpStatusCode = result.RateLimit_HttpStatusCode,
                    QuotaExceededMessage = result.RateLimit_QuotaExceededMessage,
                    RateLimitCounterPrefix = result.RateLimit_RateLimitCounterPrefix

                };
                glb.LoadBalancerOptions = new FileLoadBalancerOptions()
                {
                    Expiry = result.LoadBalancer_Expiry,
                    Key = result.LoadBalancer_Key,
                    Type = result.LoadBalancer_Type
                };
                if (result.QosEnabled)
                {
                    glb.QoSOptions = new FileQoSOptions()
                    {
                        DurationOfBreak = result.Qos_DurationOfBreak,
                        ExceptionsAllowedBeforeBreaking = result.Qos_ExceptionsAllowedBeforeBreaking,
                        TimeoutValue = result.Qos_TimeoutValue
                    };
                }
                if (result.ServiceDiscoveryEnabled)
                {
                    glb.ServiceDiscoveryProvider = new FileServiceDiscoveryProvider()
                    {
                        ConfigurationKey = result.ServiceDiscovery_ConfigurationKey,
                        Host = result.ServiceDiscovery_Host,
                        Namespace = result.ServiceDiscovery_Namespace,
                        PollingInterval = result.ServiceDiscovery_PollingInterval,
                        Port = result.ServiceDiscovery_Port,
                        Token = result.ServiceDiscovery_Token,
                        Type = result.ServiceDiscovery_Type,
                        Scheme = result.ServiceDiscovery_Scheme
                    };
                }
                else
                {
                    glb.ServiceDiscoveryProvider = null;
                }

                file.GlobalConfiguration = glb;

                if (allRoutes != null && allRoutes.Count != 0)
                {
                    var reroutelist = new List<FileRoute>();
                    foreach (var item in allRoutes)
                    {
                        var m = new FileRoute();
                        //m.AuthenticationOptions = new FileAuthenticationOptions()
                        //{
                        //    AllowedScopes = item.Authentication_AllowedScopes_List,
                        //    AuthenticationProviderKey = item.Authentication_AuthenticationProviderKey 
                        //};
                        m.FileCacheOptions = new FileCacheOptions()
                        {
                            Region = item.Cache_Region,
                            TtlSeconds = item.Cache_TtlSeconds
                        };
                        m.DelegatingHandlers = MConvert.ToList<string>(item.DelegatingHandlers);
                        m.LoadBalancerOptions = new FileLoadBalancerOptions()
                        {
                            Expiry = item.LoadBalancer_Expiry,
                            Key = item.LoadBalancer_Key,
                            Type = item.LoadBalancer_Type
                        };
                        if (result.QosEnabled)
                        {
                            m.QoSOptions = new FileQoSOptions()
                            {
                                DurationOfBreak = item.Qos_DurationOfBreak,
                                ExceptionsAllowedBeforeBreaking = item.Qos_ExceptionsAllowedBeforeBreaking,
                                TimeoutValue = item.Qos_TimeoutValue
                            };
                        }

                        if (item.HostPort != null)
                        {
                            m.DownstreamHostAndPorts = item.HostPort.ConvertTo<GetHostPortOutput, FileHostAndPort>();
                        }
                        m.RateLimitOptions = new FileRateLimitRule()
                        {
                            ClientWhitelist = item.RateLimit_WhiteList_list,
                            EnableRateLimiting = item.RateLimit_EnableRateLimiting,
                            Limit = (long)item.RateLimit_Limit,
                            Period = item.RateLimit_Period,
                            PeriodTimespan = (long)item.RateLimit_PeriodTimespan
                        };
                        //开始赋值
                        m.DownstreamPathTemplate = item.DownstreamPathTemplate;
                        m.DownstreamScheme = item.DownstreamScheme;
                        m.UpstreamHttpMethod = item.UpstreamHttpMethodList;
                        m.UpstreamPathTemplate = item.UpstreamPathTemplate;
                        m.RequestIdKey = item.RequestIdKey;
                        m.Key = item.Key;
                        m.Priority = item.Priority;
                        m.ServiceName = item.ServiceName;
                        m.ServiceNamespace = item.ServiceNamespace;
                        m.Timeout = item.Timeout;
                        m.UpstreamHost = item.UpstreamHost;
                        m.AddClaimsToRequest = item.Claims == null ? new Dictionary<string, string>() : item.Claims;
                        m.AddHeadersToRequest = item.Headers == null ? new Dictionary<string, string>() : item.Headers;
                        m.AddQueriesToRequest = item.Queries == null ? new Dictionary<string, string>() : item.Queries;
                        m.DownstreamHeaderTransform = item.HeaderDownTransform == null ? new Dictionary<string, string>() : item.HeaderDownTransform;
                        m.UpstreamHeaderTransform = item.HeaderUpTransforms == null ? new Dictionary<string, string>() : item.HeaderUpTransforms;
                        m.DownstreamHttpMethod = "get";
                        reroutelist.Add(m);

                    }
                    file.Routes = reroutelist;
                }
                return new OkResponse<FileConfiguration>(file);
            }
            catch (Exception ex)
            {
                _logger.LogError($"获取全局设置异常 ", ex);
                throw;
            }
        }

        public Task<Response> Set(FileConfiguration fileConfiguration)
        {
            _cache.AddAndDelete(_options.CachePrefix + "Configuration", fileConfiguration, TimeSpan.FromSeconds(1800), "");
            return Task.FromResult((Response)new OkResponse());

        }
    }
}
